package com.txtsqlclient.dataaccess.database.connection;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

import com.txtsqlclient.dataaccess.database.DatabaseType;

/**
 * This class is a factory, to obtain Database connections. This can be later modified to
 * implement connection pooling etc. This needs to be accessed using singleton pattern.
 * 
 * @author spadda
 */
public class ConnectionFactory {

    private static ConnectionFactory factory = null;

    /**
     * This method is required to get an instance of the connection factory.
     * 
     * @return the singleton instance of the factory.
     */
    public static ConnectionFactory getInstance() {
        if (factory == null) {
            factory = new ConnectionFactory();
        }
        return factory;
    }

    /**
     * This method is required to open a database connection.
     * 
     * @param connectionDetails
     * @return Database connection.
     * @throws ConnectionException
     */
    public Connection openConnection(ConnectionDetailsVO connectionDetails)
            throws ConnectionException {
        Connection con = null;
        String url = null;
        DatabaseType dbType = connectionDetails.getDbType();

        url = dbType.getConnectionURL();
        url = url.replaceAll("\\{ip\\}", connectionDetails.getIp());
        url = url.replaceAll("\\{database\\}", connectionDetails.getDatabase());
        try {
            Class.forName(dbType.getDriverClassName());
            con = DriverManager.getConnection(url,
                    connectionDetails.getUser(),
                    connectionDetails.getPassword());
        } catch (ClassNotFoundException cnfe) {
            throw new ConnectionException("Could not find driver class name:"
                    + dbType.getDriverClassName(), cnfe);
        } catch (SQLException sqle) {
            throw new ConnectionException("Error opening connection to the database:"
                    + connectionDetails, sqle);
        }
        return con;
    }

    /**
     * This method is required to close the database connection.
     * 
     * @param con -
     *            the database connection to be closed
     * @throws ConnectionException
     */
    public void closeConnection(Connection con) throws ConnectionException {
        try {
            if (con.isClosed()) {
                return;
            }
            con.close();
        } catch (SQLException sqle) {
            throw new ConnectionException("Error while closing database connection", sqle);
        }
    }
}
